#!/usr/bin/env python
# --*-- coding:utf-8 --*--
# author:g-y-b time:2020/5/25

from PyQt5.QtCore import QTimer, QCoreApplication
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QMainWindow, QApplication, QFileDialog
from one import Ui_Form
import cv2
import qimage2ndarray
import sys
import win32ui
import os
import numpy as np
import math


class one_ui(QMainWindow, Ui_Form):
    # 在实例化first类时，会自动调用它的初始化函数，因此，我们把想要让程序自动实现的程序功能都放在该函数下
    def __init__(self, parent=None):
        super(one_ui, self).__init__(parent)
        self.setupUi(self)
        self.PreWidgets()  # 初始化各个控件，由于某些控件需要在其它控件背后的函数运行后才能工作，因此需要先将它“disable”
        self.CallBackFunctions()  # 各个控件背后的功能函数的集合，它定义了我们在程序界面上进行某项操作后实际执行的代码

        self.original = ''
        self.myImg = ''
        self.resultImg = ''
        self.x_point = []
        self.y_point = []

        self.x_point1 = []
        self.y_point1 = []

    def PreWidgets(self):
        self.pushButton_ChooseImg.setEnabled(True)
        self.pushButton_Homography.setEnabled(False)
        self.pushButton_PerspectiveTranslate.setEnabled(False)
        self.pushButton_Resize.setEnabled(False)
        self.pushButton_Rotate.setEnabled(False)
        self.pushButton_Translate.setEnabled(False)
        self.pushButton_Confirm.setEnabled(False)
        self.pushButton_OriginalImg.setEnabled(False)

    def CallBackFunctions(self):
        self.pushButton_ChooseImg.clicked.connect(self.ChooseImg)
        self.pushButton_Translate.clicked.connect(self.ImgTranslate)
        self.pushButton_Rotate.clicked.connect(self.ImgRotate)
        self.pushButton_Resize.clicked.connect(self.ImgResize)
        self.pushButton_PerspectiveTranslate.clicked.connect(self.ImgPerspectiveTranslate)
        self.pushButton_Homography.clicked.connect(self.ImgHomography)
        self.pushButton_Confirm.clicked.connect(self.ImgConfirm)
        self.pushButton_OriginalImg.clicked.connect(self.ImgOriginal)

    def ChooseImg(self):

        dlg = win32ui.CreateFileDialog(1)
        # dlg.SetOFNInitialDir(r'D:\大三\大三下\计算机视觉\实验一\实验一（Python）\Img')
        dlg.DoModal()

        filename = dlg.GetPathName()
        print(filename)
        if filename == '':
            print("读取文件失败！")
        else:
            img = cv2.imread(filename)
            img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # 转RGB
            self.myImg = img

            img1 = cv2.imread(filename)
            self.original = cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)  # 转RGB

            img = qimage2ndarray.array2qimage(img)  # 数组转QImage
            # 使图片适应label大小
            print("读取图片成功")
            result = img  # .scaled(self.label_Image.width(), self.label_Image.height())
            self.label_Image.setPixmap(QPixmap.fromImage(result))
            self.label_Image.show()

        self.pushButton_Homography.setEnabled(True)
        self.pushButton_PerspectiveTranslate.setEnabled(True)
        self.pushButton_Resize.setEnabled(True)
        self.pushButton_Rotate.setEnabled(True)
        self.pushButton_Translate.setEnabled(True)
        self.pushButton_Confirm.setEnabled(True)
        self.pushButton_OriginalImg.setEnabled(True)

    def ImgTranslate(self):
        tx = np.float32(self.lineEdit_TranslateX.text())
        ty = np.float32(self.lineEdit_TranslateY.text())
        height, width = self.myImg.shape[0:2]
        M = np.float32([[1, 0, tx], [0, 1, ty]])
        dst = cv2.warpAffine(self.myImg, M, (width, height))
        self.resultImg = dst
        self.Img2Show(dst)

    def ImgRotate(self):
        angle = np.uint8(self.lineEdit_RotateAngle.text())
        print(type(angle))
        height, width = self.myImg.shape[0:2]
        M = cv2.getRotationMatrix2D(((width - 1) / 2.0, (height - 1) / 2.0), angle, 1)
        dst = cv2.warpAffine(self.myImg, M, (width, height))
        self.resultImg = dst
        self.Img2Show(dst)

    def ImgResize(self):
        Rx = np.float32(self.lineEdit_ResizeX.text())
        Ry = np.float32(self.lineEdit_ResizeY.text())
        dst = cv2.resize(self.myImg, None, fx=Rx, fy=Ry)
        self.resultImg = dst
        self.Img2Show(dst)

    def ImgPerspectiveTranslate(self):
        im_dst = self.myImg
        cv2.imshow("image", im_dst)
        cv2.setMouseCallback("image", self.mousePerspective)
        cv2.waitKey(0)

    def mousePerspective(self, event, x, y, flags, param):
        if event == cv2.EVENT_LBUTTONDOWN:
            im_dst = self.myImg
            # xy = "%d,%d" % (x, y)
            print(x, ',', y)
            self.x_point.append(x)
            self.y_point.append(y)
            print('x_point=', self.x_point)
            print('y_point=', self.y_point)
            cv2.circle(im_dst, (x, y), 2, (0, 0, 255), thickness=-1)
            cv2.imshow("image", im_dst)
            if len(self.x_point) % 4 == 0:
                # 图片中的书的四个角。
                pts_src = np.float32([[self.x_point[0], self.y_point[0]], [self.x_point[1], self.y_point[1]],
                                      [self.x_point[2], self.y_point[2]], [self.x_point[3], self.y_point[3]]])

                height, width = self.myImg.shape[0:2]
                pst1 = pts_src

                # pst2 = np.float32([[200, 0], [width / 4 + 200, 0], [200, height], [width / 4 + 200, height]])
                pst2 = np.float32([[0, 0], [width, 0], [0, height], [width, height]])
                # 透视变换矩阵
                M = cv2.getPerspectiveTransform(pst1, pst2)
                # 进行透视变换 self.myImg, M, dsize(width, height)分别表示源图像，变换矩阵，以及输出图像的大小
                dst = cv2.warpPerspective(self.myImg, M, (width, height))
                cv2.imshow("", dst)
                self.resultImg = dst
                self.Img2Show(dst)
                self.x_point = []
                self.y_point = []

    def ImgHomography(self):
        # 选择源图片
        dlg = win32ui.CreateFileDialog(1)
        dlg.DoModal()
        filename = dlg.GetPathName()
        print(filename)
        if filename == '':
            print("读取文件失败！")
        else:
            img = cv2.imread(filename)
            # img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)  # 转RGB
            print(img.shape)
            self.srcImg = img
            cv2.imshow("srcImage", self.srcImg)

        self.im_dst = cv2.cvtColor(self.myImg, cv2.COLOR_RGB2BGR)  # 转RGB
        cv2.imshow("image", self.im_dst)
        cv2.setMouseCallback("image", self.mouseHomography)

    def mouseHomography(self, event, x, y, flags, param):
        # im_dst = cv2.cvtColor(self.myImg, cv2.COLOR_RGB2BGR)  # 转RGB
        im_dst = self.im_dst
        if event == cv2.EVENT_LBUTTONDOWN:
            self.x_point1.append(x)
            self.y_point1.append(y)
            print('x_point=', self.x_point1)
            print('y_point=', self.y_point1)
            cv2.circle(im_dst, (x, y), 2, (0, 0, 255), thickness=-1)
            cv2.imshow("image", im_dst)
            if len(self.x_point1) % 4 == 0:
                # self.im_dst = cv2.cvtColor(self.im_dst, cv2.COLOR_BGR2RGB)  # 转RGB
                self.im_dst = self.myImg
                self.srcImg = cv2.cvtColor(self.srcImg, cv2.COLOR_BGR2RGB)  # 转RGB
                # 目的地图片中的书的四个角。
                pts_dst = np.array([[self.x_point1[0], self.y_point1[0]], [self.x_point1[1], self.y_point1[1]],
                                    [self.x_point1[2], self.y_point1[2]], [self.x_point1[3], self.y_point1[3]]])

                (a, b, c) = self.srcImg.shape
                pts_src = np.array([[0, 0], [b, 0], [0, a], [b, a]])
                # 计算单应Homography, h为变换矩阵 status是掩模
                h, status = cv2.findHomography(pts_src, pts_dst)

                # 基于单应的源图像到目的地的扭曲
                im_out = cv2.warpPerspective(self.srcImg, h, (self.im_dst.shape[1], self.im_dst.shape[0]))

                # 进行图片合并
                (a, b, c) = im_out.shape
                print(a, b, c)
                for i in range(0, a):
                    for j in range(0, b):
                        for k in range(0, c):
                            if im_out[i][j][k] != 0:
                                self.im_dst[i][j][0] = im_out[i][j][0]
                                self.im_dst[i][j][1] = im_out[i][j][1]
                                self.im_dst[i][j][2] = im_out[i][j][2]
                print(self.im_dst.shape)
                # cv2.imshow("Result Image", im_dst)
                self.resultImg = self.im_dst
                self.Img2Show(self.im_dst)
                self.x_point1 = []
                self.y_point1 = []

    def Img2Show(self, img2):
        img = qimage2ndarray.array2qimage(img2)  # 数组转QImage
        self.label_Image_2.setPixmap(QPixmap.fromImage(img))
        self.label_Image_2.show()

    def ImgConfirm(self):
        print("确认修改")
        self.myImg = self.resultImg
        img = qimage2ndarray.array2qimage(self.myImg)  # 数组转QImage
        self.label_Image.setPixmap(QPixmap.fromImage(img))
        self.label_Image.show()

    def ImgOriginal(self):
        self.myImg = self.original
        # self.Img2Show(self.myImg)
        img = qimage2ndarray.array2qimage(self.myImg)  # 数组转QImage
        self.label_Image.setPixmap(QPixmap.fromImage(img))
        self.label_Image.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ui = one_ui()
    ui.show()
    sys.exit(app.exec_())
